<!DOCTYPE html>
<html>
<head>
<script src="../../resources/gc.js"></script>
<script src="../../resources/js-test.js"></script>
</head>
<body>
<script>
description("Tests the RTCPeerConnection lifetime.");
// This test uses Chrome internals, and is therefore not
// suitable for migrating to a Web Platform Tests - test.

var dc = null;
var dc2 = null;

function dataChannelMessage(m)
{
    testPassed("dataChannelMessage");
    finishJSTest();
}

function dataChannelOpen()
{
    testPassed("dataChannelOpen");
    shouldNotThrow("dc.send('xyzzy');");
}

function connect_pcs(pc_a, pc_b) {
  pc_a.onicecandiate = function(event) {
    if (event.candidate) {
      pc_b.addIceCandidate(event.candidate);
    }
  }
  pc_b.onicecandidate = function(event) {
    if (event.candidate) {
      pc_a.addIceCandidate(event.candidate);
    }
  }
  pc_a.createOffer()
  .then(function(offer) {
    return pc_a.setLocalDescription(offer);
  })
  .then(function() {
    return pc_b.setRemoteDescription(pc_a.localDescription);
  })
  .then(function() {
    return pc_b.createAnswer();
  })
  .then(function(answer) {
    return pc_b.setLocalDescription(answer);
  })
  .then(function() {
    return pc_a.setRemoteDescription(pc_b.localDescription);
  });
}

function createPeerConnectionAndDataChannel()
{
    // The Peer Connection object is leaked
    var pc = new RTCPeerConnection();
    var pc2 = new RTCPeerConnection();
    dc = pc.createDataChannel("label");
    dc.onopen = dataChannelOpen;
    pc2.ondatachannel = function(e) {
      dc2 = e.channel;
      dc2.onmessage = dataChannelMessage;
    };
    connect_pcs(pc, pc2);
}

var pcB = null;
var observationB = null;

// Test that the PeerConnection object is gc'd if close is called.
var pcA = new RTCPeerConnection();
// Do not pass the object directly to observeGC function. This may
// remain live on this function's stack preventing GC from collecting
// it. Accessing the object inside an inner function will prevent any
// unneeded references on this function's stack.
var observationA = internals.observeGC((() => {return pcA;})());
pcA.close();
pcA = null;
asyncGC(function() {
    shouldBeTrue('observationA.wasCollected');
    observationA = null;

    // Test that the PeerConnection object is not gc'd if close is not called.
    pcB = new RTCPeerConnection();
    // Do not pass the object directly to observeGC function. This may
    // remain live on this function's stack preventing GC from collecting
    // it. Accessing the object inside an inner function will prevent any
    // unneeded references on this function's stack.
    observationB = internals.observeGC((() => {return pcB;})());
    pcB = null;
    asyncGC(function() {
        shouldBeFalse('observationB.wasCollected');
        observationB = null;

        // This test times out if the Peer connection object is garbage collected.
        createPeerConnectionAndDataChannel();
        gc();
    });
});

window.jsTestIsAsync = true;
</script>
</body>
</html>
